using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using OrchardCore.Data.EFCore;
using OrchardCore.Data.EFCore.DbContext;
using OrchardCore.Data.EFCore.Options;
using OrchardCore.Environment.Shell;
using OrchardCore.Environment.Shell.Configuration;
using OrchardCore.Environment.Shell.Scope;
using OrchardCore.Data;
using OrchardCore.Modules;

namespace Microsoft.Extensions.DependencyInjection;

/// <summary>
/// 为OrchardCoreBuilder提供EF Core数据访问功能的扩展方法
/// </summary>
public static class OrchardCoreCoreBuilderExtensions
{
    /// <summary>
    /// 添加EF Core数据访问服务
    /// </summary>
    /// <param name="builder">OrchardCoreBuilder实例</param>
    /// <returns>OrchardCoreBuilder实例</returns>
    public static OrchardCoreBuilder AddEFCoreDataAccess(this OrchardCoreBuilder builder)
    {
        builder.ConfigureServices((services, serviceProvider) =>
        {
            var configuration = serviceProvider.GetService<IShellConfiguration>();

            // 配置EF Core选项
            services.Configure<EFCoreOptions>(configuration.GetSection("OrchardCore_EFCore"));

            // 注册EF Core服务
            services.AddScoped<IEFCoreConnectionValidator, EFCoreConnectionValidator>();
            services.AddScoped<IEFCoreDataMigrationManager, EFCoreDataMigrationManager>();

            // 注册DbContext工厂
            services.AddDbContextFactory<OrchardCoreDbContext>(ConfigureDbContext);

            // 注册DbContext
            services.AddScoped<OrchardCoreDbContext>(provider =>
            {
                var factory = provider.GetRequiredService<IDbContextFactory<OrchardCoreDbContext>>();
                return factory.CreateDbContext();
            });

            // 注册数据库提供程序
            RegisterDatabaseProviders(services);

            // 注册自动迁移事件处理器
            services.AddScoped<IModularTenantEvents, EFCoreAutomaticMigrations>();
        });

        return builder;
    }

    /// <summary>
    /// 配置DbContext
    /// </summary>
    /// <param name="provider">服务提供程序</param>
    /// <param name="optionsBuilder">DbContext选项构建器</param>
    private static void ConfigureDbContext(IServiceProvider provider, DbContextOptionsBuilder optionsBuilder)
    {
        var shellSettings = provider.GetRequiredService<ShellSettings>();
        var efCoreOptions = provider.GetRequiredService<IOptions<EFCoreOptions>>().Value;
        var logger = provider.GetRequiredService<ILogger<OrchardCoreDbContext>>();

        // 根据数据库提供程序配置DbContext
        ConfigureDbContextByProvider(optionsBuilder, shellSettings);

        // 应用通用配置
        ApplyCommonConfiguration(optionsBuilder, efCoreOptions);

        // 注册日志记录器
        optionsBuilder.UseLoggerFactory(provider.GetRequiredService<ILoggerFactory>());
    }

    /// <summary>
    /// 根据数据库提供程序配置DbContext
    /// </summary>
    /// <param name="optionsBuilder">DbContext选项构建器</param>
    /// <param name="shellSettings">Shell设置</param>
    private static void ConfigureDbContextByProvider(
        DbContextOptionsBuilder optionsBuilder,
        ShellSettings shellSettings)
    {
        var connectionString = shellSettings["ConnectionString"];
        var provider = shellSettings["DatabaseProvider"];

        switch (provider)
        {
            case DatabaseProviderValue.SqlConnection:
                optionsBuilder.UseSqlServer(connectionString, sqlOptions =>
                {
                    // 移除 CommandTimeout 配置
                    sqlOptions.EnableRetryOnFailure();
                });
                break;

            case DatabaseProviderValue.Sqlite:
                optionsBuilder.UseSqlite(connectionString, sqlOptions =>
                {
                    // 移除 CommandTimeout 配置
                });
                break;

            case DatabaseProviderValue.MySql:
                optionsBuilder.UseMySql(connectionString, ServerVersion.AutoDetect(connectionString), sqlOptions =>
                {
                    // 移除 CommandTimeout 配置
                    sqlOptions.EnableRetryOnFailure();
                });
                break;

            case DatabaseProviderValue.Postgres:
                optionsBuilder.UseNpgsql(connectionString, sqlOptions =>
                {
                    // 移除 CommandTimeout 配置
                    sqlOptions.EnableRetryOnFailure();
                });
                break;

            default:
                throw new ArgumentException($"Unsupported database provider: {provider}");
        }
    }

    /// <summary>
    /// 应用通用配置
    /// </summary>
    /// <param name="optionsBuilder">DbContext选项构建器</param>
    /// <param name="efCoreOptions">EF Core选项</param>
    private static void ApplyCommonConfiguration(DbContextOptionsBuilder optionsBuilder, EFCoreOptions efCoreOptions)
    {
        // 配置详细错误
        if (efCoreOptions.EnableDetailedErrors)
        {
            optionsBuilder.EnableDetailedErrors();
        }

        // 配置敏感数据日志
        if (efCoreOptions.EnableSensitiveDataLogging)
        {
            optionsBuilder.EnableSensitiveDataLogging();
        }

        // 移除 UseMemoryCache 配置（需要额外的包）

        // 配置延迟加载
        if (efCoreOptions.EnableLazyLoading)
        {
            // 移除 UseLazyLoadingProxies 配置（需要额外的包）
        }
    }

    /// <summary>
    /// 注册数据库提供程序
    /// </summary>
    /// <param name="services">服务集合</param>
    private static void RegisterDatabaseProviders(IServiceCollection services)
    {
        // 注册SQL Server
        services.TryAddDataProvider(
            name: "SQL Server",
            value: DatabaseProviderValue.SqlConnection,
            hasConnectionString: true,
            sampleConnectionString: "Server=localhost;Database=Orchard;User Id=username;Password=password",
            hasTablePrefix: true,
            isDefault: false);

        // 注册SQLite
        services.TryAddDataProvider(
            name: "SQLite",
            value: DatabaseProviderValue.Sqlite,
            hasConnectionString: false,
            hasTablePrefix: false,
            isDefault: true);

        // 注册MySQL
        services.TryAddDataProvider(
            name: "MySQL",
            value: DatabaseProviderValue.MySql,
            hasConnectionString: true,
            sampleConnectionString: "Server=localhost;Database=Orchard;Uid=username;Pwd=password",
            hasTablePrefix: true,
            isDefault: false);

        // 注册PostgreSQL
        services.TryAddDataProvider(
            name: "PostgreSQL",
            value: DatabaseProviderValue.Postgres,
            hasConnectionString: true,
            sampleConnectionString: "Server=localhost;Port=5432;Database=Orchard;User Id=username;Password=password",
            hasTablePrefix: true,
            isDefault: false);
    }
} 
